home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1994 March / Internet Info CD-ROM (Walnut Creek) (March 1994).iso / networking / cisco / tacacsd.shar / xtacacsd / xtacacsd.c < prev   
Encoding:
C/C++ Source or Header  |  1992-08-07  |  22.1 KB  |  939 lines

  1. #define DEBUG1
  2. /*
  3.  * TACACS daemon suitable for using on Un*x systems.
  4.  *
  5.  * Janruary 1989, Greg Satz
  6.  *
  7.  * Copyright (c) 1989 by cisco Systems, Inc.
  8.  * All rights reserved.
  9.  */
  10.  
  11. #include <sys/types.h>
  12. #include <sys/socket.h>
  13. #include <sys/ioctl.h>
  14. #include <sys/file.h>
  15.  
  16. #include <netinet/in.h>
  17.  
  18. #include <stdio.h>
  19. #include <errno.h>
  20. #include <pwd.h>
  21. #include <netdb.h>
  22. #include <sys/syslog.h>
  23. #include <utmp.h>
  24. #ifdef SYSV
  25. #include <fcntl.h>
  26. #define index strchr
  27. #endif
  28. /*
  29.  * TACACS protocol defintions
  30.  */
  31. #define uchar unsigned char
  32. #define ulong unsigned long
  33. #include "tacacs.h"
  34. #define oresponse namelen
  35. #define oreason pwlen
  36.  
  37. #define    TIMEOUT        (5*60)
  38.  
  39. #define    TACACS_PORT    49
  40.  
  41. #define SEC_IN_DAY      (24*60*60)    /* seconds in a day */
  42. #define WARNING_PERIOD  14        /* days of expiration warning */
  43. #define    PASSWD_LENGTH    14        /* length of password for crypt */
  44. #define SOME_ARBITRARILY_LARGE_NUMBER 100
  45.  
  46. int debug;                /* debugging flag */
  47. int logging;                /* syslog logging flag */
  48. int stand;                /* running standalone or not */
  49. char *file;                /* validation filename */
  50. char *wtmpfile;                /* wtmp format filename */
  51. FILE *wtmpf;
  52. unsigned long querytime;        /* time query came in */
  53.  
  54. struct sockaddr_in from;
  55. int fromlen;
  56. struct hostent *hp;
  57. char buf[BUFSIZ];
  58.  
  59. char *monthname[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
  60.              "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
  61. long days_ere_month[] = {0, 31, 59, 90, 120, 151,
  62.              181, 212, 243, 273, 304, 334};
  63.  
  64. /*
  65.  * main
  66.  * We can be called from inetd or via the rc scripts directly
  67.  * Parse arguments are act appropiately.
  68.  */
  69.  
  70. main (argc, argv)
  71.     int argc;
  72.     char **argv;
  73. {
  74.     int c, on = 1, s;
  75.     struct servent *sp;
  76.     tacacstype *tp;
  77.     extern char *optarg;
  78.  
  79.     debug = 0;                /* no debugging */
  80.     logging = 0;            /* no logging */
  81.     stand = 0;                /* under inetd */
  82.     file = NULL;            /* /etc/passwd */
  83.     wtmpfile = NULL;
  84.     wtmpf = NULL;
  85. #ifdef LOG_LOCAL6
  86.     openlog("tacacsd", LOG_PID, LOG_LOCAL6);
  87. #else
  88.     openlog("tacacsd", LOG_PID);
  89. #endif
  90.     while ((c = getopt(argc, argv, "df:lsw:")) != EOF)
  91.     switch (c) {
  92.     case 'd':            /* debug */
  93.         debug = 1;
  94.         break;
  95.     case 'f':            /* file name */
  96.         file = optarg;
  97.         break;
  98.     case 'l':            /* logging */
  99.         logging = 1;
  100.         break;
  101.     case 's':            /* stand-alone */
  102.         stand = 1;
  103.         break;
  104.     case 'w':
  105.         wtmpfile = optarg;
  106.         break;
  107.     default:
  108.         fprintf(stderr, "%s: illegal switch\n", argv[0]);
  109.         exit(1);
  110.     }
  111.  
  112.     if (debug)
  113.     syslog(LOG_DEBUG, "server starting");
  114.  
  115.  
  116.     if (stand) {
  117.     /*
  118.      * Background ourselves and let go of controlling tty
  119.      */
  120.     if (!debug) {
  121.         if (fork())
  122.         exit(0);
  123.         for (c = 0; c < getdtablesize(); c++)
  124.         (void) close(c);
  125.         (void) open("/", O_RDONLY);
  126.         (void) dup2(0, 1);
  127.         (void) dup2(0, 2);
  128. #ifndef SYSV
  129.         c = open("/dev/tty", O_RDWR);
  130.         if (c >= 0) {
  131.         ioctl(c, TIOCNOTTY, (char *)0);
  132.         (void) close(c);
  133.         }
  134. #endif
  135. #ifdef LOG_LOCAL6
  136.         openlog("tacacsd", LOG_PID, LOG_LOCAL6);
  137. #else
  138.         openlog("tacacsd", LOG_PID);
  139. #endif
  140.     }
  141.     }
  142.  
  143.     if (stand) {
  144.     /*
  145.      * Pick up a socket
  146.      */
  147.     if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
  148.         syslog(LOG_ERR, "socket: %m\n");
  149.         exit(1);
  150.     }
  151.  
  152.     /*
  153.      * Get port we need to pay attention to
  154.      */
  155.     bzero((caddr_t)&from, sizeof(from));
  156. #ifdef sun
  157.     from.sin_family = AF_INET;
  158.     from.sin_addr.s_addr = INADDR_ANY;
  159. #endif
  160.     sp = getservbyname("tacacs", "udp");
  161.     if (sp == NULL)
  162.         from.sin_port = ntohs(TACACS_PORT);
  163.     else
  164.         from.sin_port = ntohs(sp->s_port);
  165.  
  166.     if (bind(s, &from, sizeof(from)) < 0) {
  167.         syslog(LOG_ERR, "bind: %m\n");
  168.         exit(1);
  169.     }
  170.     } else {
  171.     s = 0;
  172.     if (ioctl(s, FIONBIO, &on) < 0) {
  173.         syslog(LOG_ERR, "ioctl(FIONBIO): %m\n");
  174.         exit(1);
  175.     }
  176.     }
  177.  
  178.     /*
  179.      * For 4.3BSD machines, this routine sets the file the pw routines use
  180.      * to the given argument. We emulate it for others.
  181.      */
  182.     if (file != NULL)
  183.     setpwfile(file);
  184.  
  185.     if (wtmpfile != NULL) {
  186.     wtmpf = fopen(wtmpfile, "a+");
  187.     if (!wtmpf)
  188.         fprintf(stderr, "\nCan't open wtmp file \"%s\"",wtmpfile);
  189.     }
  190.     if (!stand)
  191.     alarm(TIMEOUT);
  192.  
  193. again:
  194.     fromlen = sizeof(from);
  195.     c = recvfrom(s, buf, sizeof(buf), 0, (caddr_t)&from, &fromlen);
  196.     if (c <= 0) {
  197.     if (errno == EINTR && stand)
  198.         goto again;
  199.     syslog(LOG_ERR, "recvfrom: %m\n");
  200.     exit(1);
  201.     }
  202. #ifdef DEBUG
  203.     hp = gethostbyaddr(&from.sin_addr, sizeof (struct in_addr), AF_INET);
  204.     fprintf(stderr, "main: received validation request from %s\n",
  205.         hp ? hp->h_name : (char *)inet_ntoa(from.sin_addr));
  206. #endif
  207.  
  208.     if (logging) {
  209.     hp = gethostbyaddr(&from.sin_addr, sizeof (struct in_addr), AF_INET);
  210.     syslog(LOG_INFO, "validation request from %s",
  211.         hp ? hp->h_name : (char *)inet_ntoa(from.sin_addr));
  212. #ifdef DEBUG
  213.     fprintf(stderr, "main: logged validation request\r\n");
  214. #endif
  215.     }
  216.  
  217.  
  218.     tp = (tacacstype *)buf;
  219.  
  220.     if (tp->version == TA_VERSION)
  221.     old_process(s, &from, tp);
  222.     else if (tp->version == XTA_VERSION)
  223.     new_process(s, &from, tp);
  224.     else if (logging)
  225.     syslog(LOG_INFO, "illegal version specified: %d\n", tp->version);
  226.  
  227.     if (stand)
  228.     goto again;
  229.  
  230.     exit(0);
  231. }
  232.  
  233. /*
  234.  * pw_verify
  235.  * verify the provided name/password.
  236.  */
  237. pw_verify (name, passwd, ppw)
  238. #ifdef SYSV
  239.     char name[SOME_ARBITRARILY_LARGE_NUMBER];
  240.     char passwd[SOME_ARBITRARILY_LARGE_NUMBER];
  241. #else    
  242.     char *name, *passwd;
  243. #endif
  244.     struct passwd **ppw;
  245. {
  246.     struct passwd *pw;
  247.     
  248. #ifdef DEBUG
  249.     fprintf(stderr, "pw_verify: calling setpwent\r\n");
  250. #endif
  251.  
  252.     setpwent();
  253.     if (file != NULL)
  254.     setpwfile(file);
  255. #ifdef DEBUG
  256.     fprintf(stderr, "pw_verify: returned from setpwent\r\n");
  257. #endif      
  258.     pw = getpwnam(name);
  259. #ifdef DEBUG
  260.     fprintf(stderr, "pw_verify: returned %x from getpwnam\r\n", pw);
  261. #endif      
  262.  
  263. #ifdef DEBUG
  264.     if (pw)
  265.     fprintf(stderr, "password: user %8.8s, password %13.13s\r\n",
  266.         pw->pw_name, pw->pw_passwd);
  267. #endif
  268.  
  269.  
  270.     /*
  271.      * Verify the entry.
  272.      */
  273.     if (pw != NULL && *passwd != '\0' && *pw->pw_passwd != '\0') {
  274. #ifdef SYSV
  275.     strcpy(passwd, (char *)crypt(passwd, pw->pw_passwd));
  276. #else
  277.     passwd = (char *)crypt(passwd, pw->pw_passwd);
  278. #endif    
  279. #ifdef DEBUG
  280.     fprintf(stderr, "encrypted: real %s, query %s\r\n", pw->pw_passwd, passwd);
  281. #endif
  282.     *ppw = pw;
  283.     if (strcmp(passwd, pw->pw_passwd) == 0)
  284.         return(1);
  285.     }
  286.     *ppw = NULL;
  287.     return(0);
  288. }
  289.  
  290. /*
  291.  * process
  292.  * Perform necessary stuff to do a query operation. Return ANSWER.
  293.  */
  294.  
  295. old_process (s, client, tp)
  296.     int s;
  297.     struct sockaddr_in *client;
  298.     tacacstype *tp;
  299. {
  300. #ifdef SYSV
  301.     char name[SOME_ARBITRARILY_LARGE_NUMBER];
  302.     char passwd[SOME_ARBITRARILY_LARGE_NUMBER];
  303. #else    
  304.     char *name, *passwd;
  305. #endif
  306.     struct passwd *pw;
  307.     int expired;
  308.  
  309.     querytime = time(NULL);
  310. #ifdef DEBUG
  311.     fprintf(stderr, "process: starting\r\n");
  312.     fprintf(stderr, "process: namelen %d, pwdlen %d\r\n",
  313.         tp->namelen, tp->pwlen);
  314. #endif
  315. #ifndef SYSV    
  316.     name = (char *)malloc(tp->namelen+1); 
  317. #ifdef DEBUG
  318.     fprintf(stderr, "process: malloc returned (name)\r\n");
  319.     if (name == NULL)
  320.       fprintf(stderr, "process: malloc failed on name (%d bytes)\r\n",
  321.         tp->namelen+1);
  322. #endif      
  323.     passwd = (char *)malloc(tp->pwlen+1);
  324. #ifdef DEBUG
  325.     if (passwd == NULL)
  326.       fprintf(stderr, "process: malloc failed on passwd (%d bytes)\r\n",
  327.         tp->pwlen+1);
  328. #endif      
  329.     if (name == NULL || passwd == NULL)
  330.     return;
  331. #endif /* not SYSV */
  332.     
  333.     strncpy(name, (char *)(tp + 1), tp->namelen);
  334.     name[tp->namelen] = '\0';
  335.     strncpy(passwd, (char *)(tp + 1) + tp->namelen, tp->pwlen);
  336.     if (tp->pwlen > PASSWD_LENGTH)
  337.     tp->pwlen = PASSWD_LENGTH;
  338.     passwd[tp->pwlen] = '\0';
  339.  
  340. #ifdef DEBUG
  341.     fprintf(stderr, "packet: %s %s\r\n", (char *)(tp + 1),
  342.         (char *)(tp + 1) + tp->namelen);
  343.     fprintf(stderr, "local:  %s %s\r\n", name, passwd);
  344. #endif
  345.     /*
  346.      * Assume failure
  347.      */
  348.     tp->oresponse = TA_A_REJECTED;
  349.     tp->oreason = TA_A_DENIED;
  350.     if (pw_verify(name, passwd, &pw)) {
  351.     tp->oresponse = TA_A_ACCEPTED;
  352.     tp->oreason = TA_A_NONE;
  353.     
  354.     /*
  355.      * Now check the expiration time.
  356.      */
  357.     
  358.     expired = check_expiration(pw->pw_shell);
  359.     if (expired == 2) {
  360.         tp->oresponse = TA_A_DENIED;
  361.         tp->oreason = TA_A_EXPIRING;
  362.     } else if (expired == 1)
  363.         tp->oreason = TA_A_EXPIRING;
  364.     }
  365.  
  366.  
  367. #ifdef DEBUG
  368.     fprintf(stderr, "process: logging query result\r\n");
  369. #endif
  370.     if (logging) {
  371.     if (pw != NULL)
  372.         syslog(LOG_INFO, "login query for %s (%s) %s\n", name, pw->pw_gecos,
  373.         tp->oresponse == TA_A_ACCEPTED ? "accepted" : "rejected");
  374.     else
  375.         syslog(LOG_INFO, "login query for %s %s\n", name,
  376.         tp->oresponse == TA_A_ACCEPTED ? "accepted" : "rejected");
  377.     }
  378.  
  379.     tp->type = TA_ANSWER;
  380. #ifdef DEBUG
  381.     fprintf(stderr, "process: sending query result to client\r\n");
  382. #endif
  383.     if (sendto(s, buf, sizeof(tacacstype), 0, client,
  384.     sizeof(struct sockaddr_in)) != sizeof(tacacstype))
  385.     syslog(LOG_ERR, "write: %m\n");
  386.  
  387. #ifndef SYSV
  388.     free(name);
  389.     free(passwd);
  390. #endif    
  391. #ifdef DEBUG
  392.     fprintf(stderr, "process: done\r\n");
  393. #endif
  394. }
  395.  
  396. /*
  397.  * new_process
  398.  * Perform necessary stuff to do a query operation. Return ANSWER.
  399.  */
  400.  
  401. new_process (s, client, tp)
  402.     int s;
  403.     struct sockaddr_in *client;
  404.     xtacacstype *tp;
  405. {
  406. #ifdef DEBUG
  407.     fprintf(stderr, "new_process: start\r\n");
  408. #endif
  409.     querytime = time(NULL);
  410.     switch (tp->type) {
  411.       case XTA_SLIPADDR:
  412.       case XTA_LOGIN:
  413.     xlogin(s, client, tp);
  414.     break;
  415.       case XTA_CONNECT:
  416.     xconnect(s, client, tp);
  417.     break;
  418.       case XTA_ENABLE:
  419.     xenable(s, client, tp);
  420.     break;
  421.       case XTA_LOGOUT:
  422.     xlogout(s, client, tp);
  423.     break;
  424.       case XTA_RELOAD:
  425.     xreload(s, client, tp);
  426.     break;
  427.       case XTA_SLIPON:
  428.     xslipon(s, client, tp);
  429.     break;
  430.       case XTA_SLIPOFF:
  431.     xslipoff(s, client, tp);
  432.     break;
  433.       default:
  434.     if (logging)
  435.         syslog(LOG_INFO, "illegal type specified: %d", tp->type);
  436.     }
  437. }
  438.  
  439. check_expiration(date)
  440.     char *date;
  441. {
  442.     long day, month, year, leaps, now, expiration, warning;
  443.     char monthstr[10];
  444.  
  445.     /*
  446.      * If no date or a shell, let it pass.  (Backward compatability.)
  447.      */
  448.     if (!date || (strlen(date) == 0) || (*date == '/'))
  449.     return(0);
  450.     
  451.     /*
  452.      * Parse date string.  Fail it upon error.
  453.      */
  454.     if (sscanf(date, "%s %d %d", monthstr, &day, &year) != 3)
  455.     return(2);
  456.  
  457.     /*
  458.      * Compute the expiration date in days.
  459.      */
  460.     for (month = 0; month < 12; month++)
  461.     if (strncmp(monthstr, monthname[month], 3) == 0)
  462.         break;
  463.     if (month > 11)
  464.     return(2);
  465.     leaps = (year-1969)/4 + (((year % 4) == 0) && (month > 2));
  466.     expiration = (((year-1970)*365) + days_ere_month[month] + (day-1) + leaps);
  467.     warning = expiration - WARNING_PERIOD;
  468.  
  469.     /*
  470.      * Get the current time (to the day)
  471.      */
  472.     now = querytime/SEC_IN_DAY;
  473.     
  474.     if (now > expiration)
  475.     return(2);
  476.     if (now > warning)
  477.     return(1);
  478.     return(0);
  479. }
  480.  
  481. #ifndef BSD43
  482. /*
  483.  * setpwfile
  484.  * Hack to get around the default for the pw routines using /etc/passwd
  485.  */
  486.  
  487. #include <sys/stat.h>
  488.  
  489. setpwfile (file)
  490.     char *file;
  491. {
  492.     FILE *f;
  493.     struct stat pwbuf, fbuf;
  494.     int i;
  495.     char *c;
  496.  
  497.     if (stat("/etc/passwd", &pwbuf) < 0) {
  498.     syslog(LOG_ERR, "stat: %m\n");
  499.     exit(1);
  500.     }
  501.  
  502.     setpwent();                /* open /etc/passwd */
  503.  
  504.     /*
  505.      * This loop assumes that the stdio file buffers are contiguous
  506.      * which isn't true for 4.3, but then we won't be here.
  507.      */
  508.  
  509.     for (f = stderr + 1; f < stdin + getdtablesize(); f++)
  510.         if (f->_flag & (_IOREAD|_IOWRT|_IORW) &&
  511.         fstat(fileno(f), &fbuf) >= 0 &&
  512.         pwbuf.st_dev == fbuf.st_dev &&
  513.         pwbuf.st_ino == fbuf.st_ino) {
  514.         freopen(file, "r", f);
  515.         fprintf(stderr, "hit at %d\n", fileno(f));
  516.         return;
  517.     }
  518.  
  519.     syslog(LOG_ERR, "couldn't find /etc/passwd to replace");
  520.     exit(1);
  521. }
  522. #endif
  523.  
  524. #ifdef SYSV
  525. getdtablesize()
  526. {
  527.   return(_NFILE);
  528. }
  529. #endif
  530.  
  531. wtmp_entry (line, name, host)
  532.     char *line, *name, *host;
  533. {
  534.     struct utmp entry;
  535.  
  536.     if (wtmpf == NULL)
  537.     return;
  538.  
  539.     bzero(&entry, sizeof entry);
  540.  
  541.     if (strlen(line) < sizeof entry.ut_line)
  542.     strcpy(entry.ut_line, line);
  543.     else bcopy(line, entry.ut_line, sizeof entry.ut_line);
  544.  
  545.     if (strlen(name) < sizeof entry.ut_name)
  546.     strcpy(entry.ut_name, name);
  547.     else bcopy(name, entry.ut_name, sizeof entry.ut_name);
  548.  
  549.     if (strlen(host) < sizeof entry.ut_host)
  550.     strcpy(entry.ut_host, host);
  551.     else bcopy(host, entry.ut_host, sizeof entry.ut_host);
  552.  
  553.     entry.ut_time = querytime;
  554.  
  555.     if (fwrite(&entry, sizeof entry, 1, wtmpf) != 1) {
  556.     if (logging)
  557.         syslog(LOG_ERR, "couldn't write syslog file");
  558.     } else
  559.     fflush(wtmpf);
  560.         
  561.  
  562. #ifdef DEBUG1
  563.     fprintf(stderr, "\nwtmp: %s, %s %s %d", line, name, host, querytime);
  564. #endif
  565.  
  566. }
  567.  
  568. xlogin (s, client, tp)
  569.     int s;
  570.     struct sockaddr_in *client;
  571.     xtacacstype *tp;
  572. {
  573. #ifdef SYSV
  574.     char name[SOME_ARBITRARILY_LARGE_NUMBER];
  575.     char passwd[SOME_ARBITRARILY_LARGE_NUMBER];
  576. #else    
  577.     char *name, *passwd;
  578. #endif
  579.     struct passwd *pw;
  580.     int expired;
  581.     char linename[20];
  582.  
  583. #ifdef DEBUG
  584.     fprintf(stderr, "xlogin: starting\r\n");
  585.     fprintf(stderr, "xlogin: namelen %d, pwdlen %d\r\n",
  586.         tp->namelen, tp->pwlen);
  587. #endif
  588. #ifndef SYSV    
  589.     name = (char *)malloc(tp->namelen+1); 
  590. #ifdef DEBUG
  591.     fprintf(stderr, "xlogin: malloc returned (name)\r\n");
  592.     if (name == NULL)
  593.       fprintf(stderr, "xlogin: malloc failed on name (%d bytes)\r\n",
  594.         tp->namelen+1);
  595. #endif      
  596.     passwd = (char *)malloc(tp->pwlen+1);
  597. #ifdef DEBUG
  598.     if (passwd == NULL)
  599.       fprintf(stderr, "xlogin: malloc failed on passwd (%d bytes)\r\n",
  600.         tp->pwlen+1);
  601. #endif      
  602.     if (name == NULL || passwd == NULL)
  603.     return;
  604. #endif /* not SYSV */
  605.     strncpy(name, ((char *)tp)+XTACACSSIZE, tp->namelen);
  606.     name[tp->namelen] = '\0';
  607.     strncpy(passwd, ((char *)tp)+XTACACSSIZE + tp->namelen, tp->pwlen);
  608.     if (tp->pwlen > PASSWD_LENGTH)
  609.     tp->pwlen = PASSWD_LENGTH;
  610.     passwd[tp->pwlen] = '\0';
  611.  
  612. #ifdef DEBUG
  613.     fprintf(stderr, "packet: %s %s\r\n", (char *)(tp + 1),
  614.         (char *)(tp + 1) + tp->namelen);
  615.     fprintf(stderr, "local:  %s %s\r\n", name, passwd);
  616. #endif
  617. #ifdef DEBUG1
  618.     fprintf(stderr, "\nxlogin: user %s on tty%o, host %s", name, tp->lport,
  619.         hp ? hp->h_name : (char *)inet_ntoa(from.sin_addr));        
  620. #endif
  621.     /*
  622.      * Assume failure
  623.      */
  624.     tp->response = TA_A_REJECTED;
  625.     tp->reason = TA_A_DENIED;
  626.     if (pw_verify(name, passwd, &pw)) {
  627.     tp->response = XTA_A_ACCEPTED;
  628.     tp->reason = XTA_A_NONE;
  629.     tp->uuid = pw->pw_uid;
  630.     tp->accesslist = pw->pw_gid;
  631.     tp->flags = xta_getflags(pw->pw_gecos);
  632.  
  633.     /*
  634.      * Now check the expiration time.
  635.      */
  636.  
  637.     expired = check_expiration(pw->pw_shell);
  638.     if (expired == 2) {
  639.         tp->response = TA_A_DENIED;
  640.         tp->reason = TA_A_EXPIRING;
  641.     } else if (expired == 1)
  642.         tp->reason = TA_A_EXPIRING;
  643.     }
  644.  
  645. #ifdef DEBUG
  646.     fprintf(stderr, "xlogin: logging query result\r\n");
  647. #endif
  648.     sprintf(linename, "TTY%o", tp->lport);
  649.     if (tp->response == TA_A_ACCEPTED && tp->type == XTA_LOGIN)
  650.     wtmp_entry(linename, name, 
  651.            hp ? hp->h_name : (char *)inet_ntoa(from.sin_addr));
  652.  
  653. #ifdef DEBUG
  654.     fprintf(stderr, "xlogin: sending query result to client\r\n");
  655. #endif
  656.     if (logging && tp->type == XTA_LOGIN) {
  657.     if (pw != NULL)
  658.         syslog(LOG_INFO, "xlogin query from %s %s for %s (%s) %s\n", 
  659.            hp ? hp->h_name : (char *)inet_ntoa(from.sin_addr), 
  660.            linename, name, pw->pw_gecos,
  661.         tp->response == TA_A_ACCEPTED ? "accepted" : "rejected");
  662.     else
  663.         syslog(LOG_INFO, "xlogin query from %s %s for %s %s\n",
  664.            hp ? hp->h_name : (char *)inet_ntoa(from.sin_addr),
  665.            linename, name,
  666.            tp->response == TA_A_ACCEPTED ? "accepted" : "rejected");
  667.     }
  668.     if (logging && tp->type == XTA_SLIPADDR) {
  669.     if (pw != NULL)
  670.         syslog(LOG_INFO, "slipaddress from %s %s for %s (%s) %s\n", 
  671.            hp ? hp->h_name : (char *)inet_ntoa(from.sin_addr), 
  672.            linename, name, pw->pw_gecos,
  673.         tp->response == TA_A_ACCEPTED ? "accepted" : "rejected");
  674.     else
  675.         syslog(LOG_INFO, "slipaddress from %s %s for %s %s\n",
  676.            hp ? hp->h_name : (char *)inet_ntoa(from.sin_addr),
  677.            linename, name,
  678.            tp->response == TA_A_ACCEPTED ? "accepted" : "rejected");
  679.     }
  680.     tp->type = TA_ANSWER;
  681.     if (sendto(s, buf, XTACACSSIZE, 0, client,
  682.     sizeof(struct sockaddr_in)) != XTACACSSIZE)
  683.     syslog(LOG_ERR, "write: %m\n");
  684.  
  685. #ifndef SYSV
  686.     free(name);
  687.     free(passwd);
  688. #endif    
  689. #ifdef DEBUG
  690.     fprintf(stderr, "xlogin: done\r\n");
  691. #endif
  692. }
  693.  
  694. xconnect(s, client, tp)
  695.     int s;
  696.     struct sockaddr_in *client;
  697.     xtacacstype *tp;
  698. {
  699.     struct hostent *hp1;
  700.     char *name = ((char *)tp)+XTACACSSIZE;
  701.  
  702.     name[tp->namelen] = 0;
  703.     hp1 = gethostbyaddr(&tp->dhost, sizeof (struct in_addr), AF_INET);
  704.  
  705. #ifdef DEBUG1
  706.     fprintf(stderr, "\nxconnect: user %.*s(%d) to %s:%d", tp->namelen,
  707.         ((char *)tp)+XTACACSSIZE, tp->uuid,
  708.         hp1 ? hp1->h_name : (char *)inet_ntoa(tp->dhost), tp->dport);
  709. #endif
  710.     
  711.     
  712.     if (logging)
  713.     syslog(LOG_INFO, "xconnect from %s tty%o for %s (%d) to %s:%d\n",
  714.            hp ? hp->h_name : (char *)inet_ntoa(from.sin_addr),
  715.            tp->lport, name, tp->uuid,
  716.            hp1 ? hp1->h_name : (char *)inet_ntoa(tp->dhost), tp->dport);
  717.     replyok (s, client, tp);
  718. }
  719.  
  720. xenable (s, client, tp)
  721.     int s;
  722.     struct sockaddr_in *client;
  723.     xtacacstype *tp;
  724. {
  725. #ifdef SYSV
  726.     char name[SOME_ARBITRARILY_LARGE_NUMBER];
  727.     char passwd[SOME_ARBITRARILY_LARGE_NUMBER];
  728. #else    
  729.     char *name, *passwd;
  730. #endif
  731.     struct passwd *pw;
  732.     int expired;
  733.     char linename[20];
  734.  
  735. #ifndef SYSV    
  736.     name = (char *)malloc(tp->namelen+1); 
  737.     passwd = (char *)malloc(tp->pwlen+1);
  738.     if (name == NULL || passwd == NULL)
  739.     return;
  740. #endif /* not SYSV */
  741.     
  742.     sprintf(linename, "TTY%o", tp->lport);
  743.     strncpy(name, (char *)(tp + 1), tp->namelen);
  744.     name[tp->namelen] = '\0';
  745.     strncpy(passwd, (char *)(tp + 1) + tp->namelen, tp->pwlen);
  746.     if (tp->pwlen > PASSWD_LENGTH)
  747.     tp->pwlen = PASSWD_LENGTH;
  748.     passwd[tp->pwlen] = '\0';
  749.  
  750. #ifdef DEBUG1
  751.     fprintf(stderr, "\nxenable: user %s on tty%o, host %s", name, tp->lport,
  752.         hp ? hp->h_name : (char *)inet_ntoa(from.sin_addr));        
  753. #endif
  754.     /*
  755.      * Assume failure
  756.      */
  757.     tp->response = TA_A_REJECTED;
  758.     tp->reason = TA_A_DENIED;
  759.     if (pw_verify("$enable$", passwd, &pw)) {
  760.     tp->response = XTA_A_ACCEPTED;
  761.     tp->reason = XTA_A_NONE;
  762.     tp->uuid = pw->pw_uid;
  763.     tp->accesslist = pw->pw_gid;
  764.     tp->flags = xta_getflags(pw->pw_gecos);
  765.  
  766.     /*
  767.      * Now check the expiration time.
  768.      */
  769.  
  770.     expired = check_expiration(pw->pw_shell);
  771.     if (expired == 2) {
  772.         tp->response = TA_A_DENIED;
  773.         tp->reason = TA_A_EXPIRING;
  774.     } else if (expired == 1)
  775.         tp->reason = TA_A_EXPIRING;
  776.     }
  777.  
  778.     sprintf(linename, "TTY%o", tp->lport);
  779.  
  780.     tp->type = TA_ANSWER;
  781.     if (logging)
  782.         syslog(LOG_INFO, "xenable from %s %s for %s %s\n", 
  783.            hp ? hp->h_name : (char *)inet_ntoa(from.sin_addr), 
  784.            linename, name,
  785.         tp->response == TA_A_ACCEPTED ? "accepted" : "rejected");
  786.     if (sendto(s, buf, XTACACSSIZE, 0, client,
  787.     sizeof(struct sockaddr_in)) != XTACACSSIZE)
  788.     syslog(LOG_ERR, "write: %m\n");
  789.  
  790. #ifndef SYSV
  791.     free(name);
  792.     free(passwd);
  793. #endif    
  794. }
  795.  
  796. xlogout (s, client, tp)
  797.     int s;
  798.     struct sockaddr_in *client;
  799.     xtacacstype *tp;
  800. {
  801.     char *name = ((char *)tp)+XTACACSSIZE;
  802.     char linename[20];
  803.     char *reason;
  804.  
  805.     switch(tp->reason) {
  806.       case XTA_R_IDLE:
  807.     reason = "Idle-timeout";
  808.     break;
  809.       case XTA_R_DROP:
  810.     reason = "Carrier-Drop";
  811.     break;
  812.       case XTA_R_BAD:
  813.     reason = "Bad-Passwords";
  814.     break;
  815.       case XTA_R_QUIT:
  816.     reason = "";
  817.     break;
  818.       default:
  819.     reason = "Unknown-reason";
  820.     break;
  821.     }
  822.  
  823.     name[tp->namelen] = 0;
  824.  
  825. #ifdef DEBUG1
  826.     fprintf(stderr, "\nxlogout:  user %s(%d) line %o %s", name, tp->uuid,
  827.         tp->lport, reason);
  828. #endif
  829.     sprintf(linename, "TTY%o", tp->lport);
  830.     if (logging)
  831.     syslog(LOG_INFO, "xlogout from %s %s, user %s(%d) %s\n",
  832.            hp ? hp->h_name : (char *)inet_ntoa(from.sin_addr), linename,
  833.            name, tp->uuid, reason);
  834.     wtmp_entry(linename, "", 
  835.            hp ? hp->h_name : (char *)inet_ntoa(from.sin_addr));
  836.     replyok (s, client, tp);
  837. }
  838.  
  839. xreload(s, client, tp)
  840.     int s;
  841.     struct sockaddr_in *client;
  842.     xtacacstype *tp;
  843. {
  844. #ifdef DEBUG1
  845.     fprintf(stderr, "\nxreload: host %s",
  846.         hp ? hp->h_name : (char *)inet_ntoa(from.sin_addr));
  847. #endif
  848.     if (logging)
  849.     syslog(LOG_INFO, "system reload from %s\n",
  850.            hp ? hp->h_name : (char *)inet_ntoa(from.sin_addr));
  851.     wtmp_entry("~", "", hp ? hp->h_name : (char *)inet_ntoa(from.sin_addr));
  852.     replyok (s, client, tp);
  853. }
  854.  
  855. xslipon(s, client, tp)
  856.     int s;
  857.     struct sockaddr_in *client;
  858.     xtacacstype *tp;
  859. {
  860.     struct hostent *hp1;
  861.     char linename[20];
  862.     char *name = (char *) (tp + 1);
  863.  
  864.     name[tp->namelen] = 0;
  865.  
  866.     hp1 = gethostbyaddr(&tp->dhost, sizeof (struct in_addr), AF_INET);
  867.  
  868. #ifdef DEBUG1
  869.     fprintf(stderr, "\nxslipon:  user %.*s(%d) line %o slip address %s",
  870.         tp->namelen, ((char *)tp)+XTACACSSIZE, tp->uuid, tp->lport, 
  871.         hp1 ? hp1->h_name : (char *)inet_ntoa(tp->dhost));
  872.  
  873. #endif
  874.     sprintf(linename, "SLIP%o", tp->lport);
  875.     wtmp_entry(linename, name, hp1 ? hp1->h_name : (char *)inet_ntoa(tp->dhost));
  876.     if (logging)
  877.     syslog(LOG_INFO, "xslipon from %s %s for  user %s(%d) address %s\n",
  878.            hp ? hp->h_name : (char *)inet_ntoa(from.sin_addr), linename,
  879.            name, tp->uuid,
  880.            hp1 ? hp1->h_name : (char *)inet_ntoa(tp->dhost));
  881.  
  882.  
  883.     replyok (s, client, tp);
  884. }
  885.  
  886.  
  887. xslipoff(s, client, tp)
  888.     int s;
  889.     struct sockaddr_in *client;
  890.     xtacacstype *tp;
  891. {
  892.     struct hostent *hp1;
  893.     char linename[20];
  894.     char *name;
  895.  
  896.     hp1 = gethostbyaddr(&tp->dhost, sizeof (struct in_addr), AF_INET);
  897.  
  898.  
  899. #ifdef DEBUG1
  900.     fprintf(stderr, "\nxslipoff:  user %.*s(%d) line %o slip address %s",
  901.         tp->namelen, ((char *)tp)+XTACACSSIZE, tp->uuid, tp->lport,
  902.         hp1 ? hp1->h_name : (char *)inet_ntoa(tp->dhost));
  903.  
  904. #endif
  905.     sprintf(linename, "SLIP%o", tp->lport);
  906.     wtmp_entry(linename, "",  hp1 ? hp1->h_name : (char *)inet_ntoa(tp->dhost));
  907.     name = (char *) (((char *)tp)+XTACACSSIZE);
  908.     name[tp->namelen] = 0;    if (logging)
  909.     if (logging)
  910.     syslog(LOG_INFO, "xslip off from %s %s for %s(%d) address %s\n",
  911.            hp ? hp->h_name : (char *)inet_ntoa(from.sin_addr), linename,
  912.            name, tp->uuid,
  913.            hp1 ? hp1->h_name : (char *)inet_ntoa(tp->dhost));
  914.  
  915.     replyok (s, client, tp);
  916. }
  917.  
  918. xta_getflags (string)
  919.     char * string;
  920. {
  921.     return(0);
  922. }
  923.  
  924. /*
  925.  * Send an "ok" reply to client (for things like reload, logout)
  926.  */
  927. replyok (s, client, tp)
  928.     int s;
  929.     struct sockaddr_in *client;
  930.     xtacacstype *tp;
  931. {
  932.     tp->response = XTA_A_ACCEPTED;
  933.     tp->reason = XTA_A_NONE;
  934.     tp->type = TA_ANSWER;
  935.     if (sendto(s, buf, XTACACSSIZE, 0, client,
  936.     sizeof(struct sockaddr_in)) != XTACACSSIZE)
  937.     syslog(LOG_ERR, "write: %m\n");
  938. }
  939.